﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Ribbon.Core.Event;
using Graphic = Ribbon.Core.Graphics.GraphicHelper;

namespace Ribbon.Core
{
    public class RibbonFillColorItem : IRibbonItem
    {
        public RibbonFillColorItem(string name)
        {
            this.name = name;

            this.text = name;

            this.foreColor = Color.Black;

            this.backColor = Color.FromArgb(238, 238, 242);

            this.borderColor = Color.FromArgb(209, 209, 209);

            this.selectBackColor = Color.FromArgb(209, 209, 209);

            this.radiu = 5;

            this.contentImage = new Bitmap(60, 60);// Properties.Resource.A;

            this.defaultBackColor = Color.FromArgb(242, 242, 242);

            this.selectBorderColor = Color.FromArgb(209, 209, 209);

            this.selectColor = Color.Yellow;

            this.selectBorderColor = ChangeColorBrightness(this.selectColor, 0.5f);

            this.leftColor = Color.FromArgb(238, 238, 242);

            this.rightColor = Color.FromArgb(238, 238, 242);

            this.imageSize = 15;

            //Console.WriteLine(sb.ElapsedMilliseconds);

            this.colors = new ColorPopup();
        }

        RibbonGroup parent;

        public RibbonGroup Parent
        {
            get
            {
                return parent;
            }
            set
            {
                parent = value;

                if (parent != null)
                {
                    Resize();
                }
            }
        }

        bool isMouseHover;

        public bool IsMouseHover
        {
            get
            {
                return isMouseHover;
            }
            set
            {
                isMouseHover = value;
            }
        }

        private bool maxImage;

        public bool MaxImage
        {
            get { return maxImage; }
            set { maxImage = value; }
        }

        /// <summary>
        /// 边界框
        /// </summary>
        private Rect rect;

        public Rect Rect
        {
            get { return rect; }
            set { rect = value; }
        }

        /// <summary>
        /// 坐标
        /// </summary>
        private PointF location;

        public PointF Location
        {
            get { return location; }
            set { location = value; }
        }

        /// <summary>
        /// 大小
        /// </summary>
        private SizeF size;

        public SizeF Size
        {
            get { return size; }
            set { size = value; }
        }

        /// <summary>
        /// 文本
        /// </summary>
        private string text;

        public string Text
        {
            get { return text; }
            set { text = value; }
        }

        private Font font;

        /// <summary>
        /// 字体
        /// </summary>
        public Font Font
        {
            get { return font; }
            set { font = value; }
        }

        /// <summary>
        ///
        /// </summary>
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private Bitmap image;

        public Bitmap Image
        {
            get { return image; }
            set { image = value; }
        }

        private int borderSize;

        public int BorderSize
        {
            get { return borderSize; }
            set { borderSize = value; }
        }

        private Color borderColor;

        public Color BorderColor
        {
            get { return borderColor; }
            set { borderColor = value; }
        }

        private Color backColor;

        public Color BackColor
        {
            get { return backColor; }
            set { backColor = value; }
        }

        private Color selectBackColor;

        public Color SelectBackColor
        {
            get { return selectBackColor; }
            set { selectBackColor = value; }
        }

        private Color foreColor;

        public Color ForeColor
        {
            get { return foreColor; }
            set { foreColor = value; }
        }

        private float radiu;

        public float Radiu
        {
            get { return radiu; }
            set { radiu = value; }
        }

        private float imageSize;

        public float ImageSize
        {
            get { return imageSize; }
            set { imageSize = value; }
        }

        public event MouseClickDelegate MouseClick;

        public event MouseEnterDelegate MouseEnter;

        public event MouseMoveDelegate MouseMove;

        public event MouseLeaveDelegate MouseLeave;

        public event ColorChangedDelegate PickColorEvent;

        private Color selectColor;

        private Color rightColor;

        public Color RightColor
        {
            get { return rightColor; }
            set { rightColor = value; }
        }

        private Color leftColor;

        public Color LeftColor
        {
            get { return leftColor; }
            set { leftColor = value; }
        }

        private Color defaultBackColor;

        public Color DefaultBackColor
        {
            get { return defaultBackColor; }
            set { defaultBackColor = value; }
        }

        private Color selectBorderColor;

        public Color SelectBorderColor
        {
            get { return selectBorderColor; }
            set { selectBorderColor = value; }
        }

        private Rect leftRect;

        private Rect rightRect;

        private Rect contentRect;

        private Image dropImage;

        public Image DropImage
        {
            get { return dropImage; }
            set { dropImage = value; }
        }

        private Image contentImage;

        public Image ContentImage
        {
            get { return contentImage; }
            set { contentImage = value; }
        }

        internal Color GetSelectColor()
        {
            return selectColor;
        }

        public void UpdateColor(Color clr)
        {
            this.selectColor = clr;
            this.selectBorderColor = ChangeColorBrightness(this.selectColor, 0.5f);
        }

        public void Resize()
        {
            if (this.Font == null)
                this.Font = parent.Font;

            this.rect = new Rect(parent.GroupRect.X + this.location.X, parent.GroupRect.Y + this.location.Y, this.size.Width, this.size.Height);

            //按数值取长宽高绘制时在高分屏里会位置错乱  这里我们采用比例法  将需要绘制的分成三部分

            //左边的宽度占整个宽度的比值
            float leftScale = 0.7f;

            //左边内容中上面的文字占高度比值
            float leftUpScale = 0.65f;

            leftRect = new Rect(this.rect.X + 1, this.rect.Y + 1, this.rect.Width * leftScale - 1, this.rect.Height - 2);

            rightRect = new Rect(leftRect.X + leftRect.Width, this.rect.Y + 1, this.rect.Width - leftRect.Width - 2, this.rect.Height - 2);

            contentRect = new Rect(leftRect.X + (leftRect.Width - this.imageSize) / 2f, leftRect.Y + 1f, this.imageSize, this.rect.Height * leftUpScale);

            if (parent.GroupRect.X + parent.GroupRect.Width < this.rect.X + this.rect.Width)
            {
                parent.GroupRect.Width += (this.rect.X + this.rect.Width + 5f) - (parent.GroupRect.X + parent.GroupRect.Width);
            }
        }

        public void OnPaint(System.Drawing.Graphics g)
        {
            if (this.isMouseHover)
            {
                using (SolidBrush bru_Background = new SolidBrush(selectBackColor))
                {
                    if (this.radiu > 1)
                    {
                        using (System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath())
                        {
                            path.AddLine(this.rect.X, this.rect.Y + this.rect.Height - this.radiu, this.rect.X, this.rect.Y + this.radiu);

                            path.AddArc(this.rect.X, this.rect.Y, this.radiu, this.radiu, 180, 90);

                            path.AddLine(this.rect.X + this.radiu, this.rect.Y, this.rect.X + this.rect.Width - this.radiu, this.rect.Y);

                            path.AddArc(this.rect.X + this.rect.Width - this.radiu, this.rect.Y, this.radiu, this.radiu, 270, 90);

                            path.AddLine(this.rect.X + this.rect.Width, this.rect.Y + this.radiu, this.rect.X + this.rect.Width, this.rect.Y + this.rect.Height - this.radiu);

                            path.AddArc(this.rect.X + this.rect.Width - this.radiu, this.rect.Y + this.rect.Height - this.radiu, this.radiu, this.radiu, 0, 90);

                            path.AddLine(this.rect.X + this.rect.Width - this.radiu, this.rect.Y + this.rect.Height, this.rect.X + this.radiu, this.rect.Y + this.rect.Height);

                            path.AddArc(this.rect.X, this.rect.Y + this.rect.Height - this.radiu, this.radiu, this.radiu, 90, 90);

                            g.FillPath(bru_Background, path);
                        }
                    }
                    else
                    {
                        g.FillRectangle(bru_Background, (int)this.rect.X, (int)this.rect.Y, (int)this.rect.Width, (int)this.rect.Height);
                    }
                }
            }

            using (Brush bru_Left = new SolidBrush(leftColor))
            {
                g.FillRectangle(bru_Left, this.leftRect.X, this.leftRect.Y, this.leftRect.Width, this.leftRect.Height);
            }

            using (Brush bru_Right = new SolidBrush(rightColor))
            {
                g.FillRectangle(bru_Right, this.rightRect.X, this.rightRect.Y, this.rightRect.Width, this.rightRect.Height);
            }

            using (Pen p_border = new Pen(borderColor, 2))
            {
                
            }

            //Draw Base Image
            g.DrawImage(this.contentImage, this.contentRect.X, this.contentRect.Y, this.contentRect.Width, this.contentRect.Height);

            using (Brush bru = new SolidBrush(selectColor))
            {
                RectangleF rec_Color = new RectangleF(contentRect.X, contentRect.Y + contentRect.Height + 0.5f, contentRect.Width, 2.5f);

                using (Pen p_border = new Pen(selectBorderColor, 1))
                {
                    g.FillRectangle(bru, rec_Color);

                    g.DrawRectangle(p_border, rec_Color.X - 1f, rec_Color.Y - 1f, rec_Color.Width + 1f, rec_Color.Height + 1f);
                }
            }

            //Draw Arraw drop down
            g.DrawImage(this.dropImage, new RectangleF(rightRect.X - 3, rightRect.Y + 2.5f, 16, 16));
        }

        public void Refresh()
        {
            this.parent.Refresh();
        }

        public void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                //在右边区域选中
                if (e.X >= rightRect.X)
                {
                    ShowPicker();
                }
                //在左边区域点击鼠标
                else
                {
                    leftColor = Color.FromArgb(238, 238, 242);

                    this.Refresh();

                    leftColor = Color.FromArgb(240, 245, 255);

                    this.Refresh();

                    if (PickColorEvent != null)
                    {
                        PickColorEvent(this, new ColorEventArgs(this.selectColor));
                    }

                    leftColor = Color.FromArgb(209, 209, 209);

                    this.Refresh();
                }
            }

            if (MouseClick != null)
            {
                MouseClick(this, e);
            }
        }

        public void OnMouseEnter(MouseEventArgs e)
        {
            if (this.MouseEnter != null)
            {
                this.MouseEnter(this, e);
            }
        }

        public void OnMouseMove(MouseEventArgs e)
        {
            if (e.X >= rightRect.X)
            {
                leftColor = Color.FromArgb(240, 245, 255);
                rightColor = Color.FromArgb(219, 219, 219);
            }
            else
            {
                rightColor = Color.FromArgb(240, 245, 255);
                leftColor = Color.FromArgb(219, 219, 219);
            }
            this.Refresh();
        }

        PopupWindow popupWnd;

        private ColorPopup colors;

        private void ShowPicker()
        {
            popupWnd = new PopupWindow(colors);

            colors.OnPickColor += OnColorChanged;

            Point pt = this.parent.Parent.Parent.PointToScreen(new Point((int)this.rect.X, (int)this.rect.Y + (int)this.rect.Height + 2));

            popupWnd.ColorChanged += new ColorChangedDelegate(OnColorChanged);

            popupWnd.Show(pt);
        }

        protected void OnColorChanged(object sender, ColorEventArgs e)
        {
            if (PickColorEvent != null && e.SelectColor != this.selectColor)
            {
                this.selectColor = e.SelectColor;
                this.selectBorderColor = ChangeColorBrightness(this.selectColor, 0.5f);
                PickColorEvent(this, new ColorEventArgs(this.selectColor));
            }
            else
                this.selectColor = e.SelectColor;

            this.Refresh();
        }

        private Color ChangeColorBrightness(Color color, float correctionFactor)
        {
            if (GetLight(color) > 0.179)
            {
                return Color.FromArgb(209, 209, 209);
            }
            else
            {
                return Color.White;
            }
        }

        private double GetLight(double c)
        {
            c = c / 255.0;
            if (c <= 0.03928)
                c = c / 12.92;
            else
                c = Math.Pow((c + 0.055f) / 1.055f, 2.4f);

            return c;
        }

        private double GetLight(Color c)
        {
            return 0.2126 * GetLight(c.R) + 0.7152 * GetLight(c.G) + 0.0722 * GetLight(c.B);
        }

        public void OnMouseLeave(MouseEventArgs e)
        {
            this.leftColor = this.backColor;
            this.rightColor = this.backColor;
            this.Refresh();
        }
    }
}
